package net.chenlin.dp.ids.client.util;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;

/**
 *  xml工具类
 * @author zcl<yczclcn@163.com>
 */
public class XmlUtil {

    /** 当读取多个xml文件时，缓存xml阅读器 **/
    private static HashMap<String, XmlUtil> xmlMap = new HashMap<>(1);

    /** xml根节点 **/
    private Node root;

    /** xpath解析器 **/
    private XPath xPath;

    /** 加载时间 **/
    private Date loadTime;

    /** 缓存过期时间 **/
    private static final Integer EXPIRED = 60 * 1000;

    private XmlUtil() { }

    public static synchronized XmlUtil getInstance(String name, String tag) {
        XmlUtil xmlUtil = xmlMap.get(name);
        if (null == xmlUtil) {
            xmlUtil = new XmlUtil().init(name, tag);
        }
        // 判断文件是否打开超过1分钟
        if ((System.currentTimeMillis() - xmlUtil.getLoadTime().getTime()) > EXPIRED) {
            xmlUtil = new XmlUtil().init(name, tag);
            xmlMap.put(name, xmlUtil);
        }
        return xmlUtil;
    }

    /**
     * 读取节点
     * @param element
     * @return
     */
    public Node getNode(String element) {
        return getNode(element, root);
    }

    /**
     * 读取子节点集合
     * @param element
     * @return
     */
    public NodeList getList(String element) {
        try {
            return (NodeList) xPath.evaluate(element, root, XPathConstants.NODESET);
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读取字符串
     * @param element
     * @return
     */
    public String getStr(String element) {
        try {
            return (String) xPath.evaluate(element, root, XPathConstants.STRING);
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读取指定节点
     * @param element
     * @param selectNode
     * @return
     */
    private Node getNode(String element, Object selectNode) {
        try {
            return (Node) xPath.evaluate(element, selectNode, XPathConstants.NODE);
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 初始化时间
     * @return
     */
    private Date getLoadTime() {
        return loadTime;
    }

    /**
     * 初始化文档和根节点
     * @param name
     * @param tag
     * @return
     */
    private XmlUtil init(String name, String tag) {
        try {
            this.loadTime = new Date();
            this.xPath = XPathFactory.newInstance().newXPath();
            DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
            Document document = documentBuilder.parse(inputStream);
            if (null == document) {
                throw new RuntimeException("读取配置文件异常");
            }
            this.root = getNode(tag, document);
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
        return this;
    }

}
